// Onlyafly's library of javascript extras

//////// EXTRAS NAMESPACE

var Extras = {};

// Extras.range
//
// Added: 12/11/2008
// Author: Kevin Albrecht
//
// Generates a range from low to high, inclusive.
//
// Parameters:
//   step (optional)
Extras.range = function(low, high, step) {
  var matrix = [];
  var inival, endval, plus;
  var walker = step || 1;
  var chars  = false;

  if ( typeof(low) == "number" && typeof(high) == "number" ) {
      inival = low;
      endval = high;
  } else if ( typeof(low) == "string" && typeof(high) == "string" ) {
      chars = true;
      inival = low.charCodeAt ( 0 );
      endval = high.charCodeAt ( 0 );
  } else {
      inival = ( isNaN ( low ) ? 0 : low );
      endval = ( isNaN ( high ) ? 0 : high );
  }

  plus = ( ( inival > endval ) ? false : true );
  if ( plus ) {
      while ( inival <= endval ) {
          matrix.push ( ( ( chars ) ? String.fromCharCode ( inival ) : inival ) );
          inival += walker;
      }
  } else {
      while ( inival >= endval ) {
          matrix.push ( ( ( chars ) ? String.fromCharCode ( inival ) : inival ) );
          inival -= walker;
      }
  }

  return matrix;
};

// Inclusive between
Extras.isBetween = function(low, value, high) {
  if (low <= value && value <= high) {
    return true;
  }
  else {
    return false;
  }
};

Extras.isInteger = function(value) {
  if (Math.floor(value) === value) {
    return true;
  }
  else {
    return false;
  }
};

// Function.prototype.hasInstances
//
// Added: 12/11/2008
// Author: Kevin Albrecht
// 
// Checks that each argument is an instance of the function
if (!Function.prototype.hasInstances)
{
  Function.prototype.hasInstances = function()
  {
    if (arguments.length === 0) {
      throw new TypeError();
    }
  
    for (var i = 0; i < arguments.length; i++) {
      if (!(arguments[i] instanceof this)) {
        return false;
      }
    }
    
    return true;
  };
}

// Array.mapMethod
//
// Added: 12/3/2008
// Author: Kevin Albrecht
if (!Array.prototype.mapMethod)
{
  Array.prototype.mapMethod = function(methodName)
  {
    var len = this.length;
    if (typeof methodName != "string")
      throw new TypeError();

    var res = new Array(len);
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        res[i] = this[i][methodName]();
    }

    return res;
  };
}

// Array.map
//
// Added: 12/3/2008
// Author: Mozilla 
// See: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/map
//  
// 'map' is a JavaScript extension to the ECMA-262 standard; as such it may
// not be present in other implementations of the standard. You can work around
// this by inserting the following code at the beginning of your scripts,
// allowing use of 'map' in ECMA-262 implementations which do not natively
// support it. This algorithm is exactly the one used in Firefox and
// SpiderMonkey.
if (!Array.prototype.map)
{
  Array.prototype.map = function(fun) // fun,[thisp]
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

    return res;
  };
}

// Array.reduce
//
// Added: 12/3/2008
// Author: Mozilla, with fixes by Kevin Albrecht
// See: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
//  
// 'reduce' is a JavaScript extension to the ECMA-262 standard; as such it may
// not be present in other implementations of the standard. You can work around
// this by inserting the following code at the beginning of your scripts,
// allowing use of reduce in ECMA-262 implementations which do not natively
// support it. This algorithm is exactly the one used in Firefox and
// SpiderMonkey.  
if (!Array.prototype.reduce)
{
  Array.prototype.reduce = function(fun) // fun,[initial]
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    // no value to return if no initial value and an empty array
    if (len === 0 && arguments.length === 1)
      throw new TypeError();

    var i = 0;
    if (arguments.length >= 2)
    {
      var rv = arguments[1];
    }
    else
    {
      do
      {
        if (i in this)
        {
          rv = this[i];
          i++;
          break;
        }

        // if array contains no values, no initial value to return
        i++;
        if (i >= len)
          throw new TypeError();
      }
      while (true);
    }

    for (; i < len; i++)
    {
      if (i in this)
        rv = fun.call(null, rv, this[i], i, this);
    }

    return rv;
  };
}

// Array.reduceRight
//
// Added: 12/3/2008
// Author: Mozilla 
// See: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
//  
// 'reduceRight' is a JavaScript extension to the ECMA-262 standard; as such it
// may not be present in other implementations of the standard. You can work
// around this by inserting the following code at the beginning of your scripts,
// allowing use of reduce in ECMA-262 implementations which do not natively
// support it. This algorithm is exactly the one used in Firefox and
// SpiderMonkey.
if (!Array.prototype.reduceRight)
{
  Array.prototype.reduceRight = function(fun) // fun,[initial]
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    // no value to return if no initial value, empty array
    if (len === 0 && arguments.length === 1)
      throw new TypeError();

    var i = len - 1;
    if (arguments.length >= 2)
    {
      var rv = arguments[1];
    }
    else
    {
      do
      {
        if (i in this)
        {
          i--;
          rv = this[i];
          break;
        }

        // if array contains no values, no initial value to return
        i--;
        if (i < 0)
          throw new TypeError();
      }
      while (true);
    }

    for (; i >= 0; i--)
    {
      if (i in this)
        rv = fun.call(null, rv, this[i], i, this);
    }

    return rv;
  };
}

if (!Array.prototype.contains){
  Array.prototype.contains = function(obj) {
    var len = this.length;
    for (var i = 0; i < len; i++) {
      if (this[i]===obj) {
        return true;
      }
    }
    return false;
  };
}

if(!Array.prototype.containsAny){
  Array.prototype.containsAny = function(obj) {
    if (isArray(obj)) {
      for (var i=0; i<obj.length; i++){
        if (this.contains(obj[i])) {
          return true;
        }
      }
      return false;
    }
    else {
      throw new TypeError();
    }
  };
}

// Array.forEach
//
// Added: 12/10/2008
// Author: Mozilla 
// See: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/forEach
//  
// 'forEach' is a JavaScript extension to the ECMA-262 standard; as such it
// may not be present in other implementations of the standard. You can work
// around this by inserting the following code at the beginning of your scripts,
// allowing use of 'forEach' in ECMA-262 implementations which do not natively
// support it. This algorithm is exactly the one used in Firefox and
// SpiderMonkey.
if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun) // (fun,[thisp])
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}